
#include "./app_can_master.h"

struct can_dev_t *comm_dev;//通信设备
extern uint16_t voutSetVal,ioutSetVal;
struct can_msg_ext_id_t  mgs_ext_id;
uint8_t limit_flag = 0;//限制标志 bit0 限流 bit1 均流
uint16_t  canVoutSetVal = 0;//设置值
uint16_t  canLimitIval = 0;//限流值
uint16_t canAvrIoutval;
uint8_t vtest = 0;
extern uint32_t canSlaveAddr;
static uint8_t canTxBuf[8]={0};
/**
 * 根据输入源地址目的地址和版本号得到一个扩展地址
*/
uint32_t can_set_msg_ext_id(void)
{
     /**
     * bit | 27:22  | 21:20  |   19:0     |
     *     | 命令号 |目的地址|   源地址   |
     *     | 6bits  |2bits   |   20bits   |
     *    
    */
    uint32_t ret = 0;
    //mgs_ext_id.cmd=mgs_ext_id.cmd&0x3f;
    ret |=(mgs_ext_id.cmd<<22)|(mgs_ext_id.master_addr<<20)|mgs_ext_id.slave_addr;
    return ret;
    
}


/**
 * @brief 设置模块 电压
 *
 * @param num  模块号
 * @param vout 电压值
*/
sn_err_t can_app_set_mod_vout(struct can_dev_t *dev,uint8_t num,uint32_t vout)
{

    mgs_ext_id.cmd  = CAN_CMD_DEVICE_HOST_SET_VOUT;
    mgs_ext_id.master_addr  = CAN_MASTER_ADDR;
    mgs_ext_id.slave_addr =dev->can_dev_list[num].addr;
    dev->obj.tx_id=can_set_msg_ext_id();
    dev->set_ide(dev,1);//设置扩展帧
    /**
     * @brief 在获取模块信息时，携带均流信息
     * 
     */
    canTxBuf[0] = vout;
    canTxBuf[1] = vout>>8;
    canTxBuf[2] = 0;
    canTxBuf[3] = 0;
    dev->tx_msg_func(dev,canTxBuf,8);//返回当前设备状态 

    return SN_OK;
}
/**
 * 
 * @brief 设置系统开关机
 * 
 * @param state 0 关机 1 开机
 * 
*/
sn_err_t can_app_set_sys_power(struct can_dev_t *dev,uint8_t state)
{

    mgs_ext_id.cmd  = CAN_CMD_BROADCAST_HOST_SET_DEV;
    mgs_ext_id.master_addr = CAN_BROADCAST_ADDR;
    mgs_ext_id.slave_addr = CAN_BROADCAST_ADDR;
    dev->obj.tx_id=can_set_msg_ext_id();
    dev->set_ide(dev,1);//设置扩展帧

    if(state == 0xff){
         canTxBuf[0] = 1;
    }
    else{
         canTxBuf[0] = 0;
    }
    dev->tx_msg_func(dev,canTxBuf,8);//返回当前设备状态 
    return  SN_OK;
}
/**
 * @brief 获取模块开关机
 */
sn_err_t can_app_set_mod_power(struct can_dev_t *dev,uint32_t num,uint8_t state)
{
  
    mgs_ext_id.cmd  = CAN_CMD_DEVICE_HOST_SET_DEV_POWER;
    mgs_ext_id.master_addr  = CAN_MASTER_ADDR;
    mgs_ext_id.slave_addr =dev->can_dev_list[num].addr;

    dev->obj.tx_id=can_set_msg_ext_id();
    dev->set_ide(dev,1);//设置扩展帧

    if(state == 0xff){
          canTxBuf[0] = 1;
    }
    else{
         canTxBuf[0] = 0;
    }
    dev->tx_msg_func(dev,canTxBuf,8);//返回当前设备状态 
    return SN_OK;
}

/**
 * @brief 获取模块输出电压 
 * 
 */
sn_err_t can_app_get_mod_vout(struct can_dev_t *dev,uint32_t num)
{
  
     uint16_t tmp_v,tmp_i;

     tmp_v = 4000;
     tmp_i =dev->can_dev_list[num].ave_i_val;

    mgs_ext_id.cmd  = CAN_CMD_DEVICE_HOST_GET_MOD_VOUT_IOUT;
    mgs_ext_id.master_addr  = CAN_MASTER_ADDR;
    mgs_ext_id.slave_addr =dev->can_dev_list[num].addr;
    dev->obj.tx_id=can_set_msg_ext_id();
    dev->set_ide(dev,1);//设置扩展帧
    
     
    /**
     * @brief 在获取模块信息时，携带均流信息
     * 
     */
    canTxBuf[0] = dev->get_limit_flag(dev);
    canTxBuf[1] = tmp_v;
    canTxBuf[2] = tmp_v>>8;
    canTxBuf[3] = tmp_i;
    canTxBuf[4] = tmp_i>>8;
    dev->tx_msg_func(dev,canTxBuf,8);//返回当前设备状态 
    return SN_OK;
}

sn_err_t can_app_get_mod_state(struct can_dev_t *dev,uint32_t num)
{
    
    can_app_get_mod_vout(dev,num);
  //  sn_delay_ms(CAN_DELAY_MS);
    return SN_OK;
}

/**
 * 根据命令 解析出数据内容，并将这些数据填到模块的结构体中  
 * index 模块索引
*/
static sn_err_t can_read_slave_device_info(struct can_dev_t *dev,uint8_t index)
{
    uint16_t val = 0;
  
    dev->can_dev_list[index].on = 1;
    dev->can_dev_list[index].on_cnt += 1;
    if(dev->can_dev_list[index].on_cnt>CAN_MOD_ON_COUNT)
    {
      dev->can_dev_list[index].on_cnt = CAN_MOD_ON_COUNT;
    }
    switch(comm_dev->obj.cmd_num){
    case CAN_CMD_DEVICE_HOST_GET_MOD_VOUT_IOUT  : 
        val =comm_dev->obj.RX[0]|(comm_dev->obj.RX[1]<<8); 
        dev->can_dev_list[index].power = (val>>15)&0x01;
        dev->can_dev_list[index].mod_vout  = val&0x7fff;
        dev->can_dev_list[index].mod_iout  =  comm_dev->obj.RX[2]|(comm_dev->obj.RX[3]<<8);
        dev->can_dev_list[index].ac_ab_val =  comm_dev->obj.RX[4]|(comm_dev->obj.RX[5]<<8);
        dev->can_dev_list[index].ac_ca_val =  dev->can_dev_list[index].ac_ab_val;
        dev->can_dev_list[index].ac_bc_val = dev->can_dev_list[index].ac_ab_val;
        dev->can_dev_list[index].mod_state[0] = comm_dev->obj.RX[6];
        dev->can_dev_list[index].mod_state[1] = comm_dev->obj.RX[7];
    break;
    default:    
    break;
    }
    return SN_OK;
}

/*
 * @检查can 设备地址 是否在canlist 中
 * return 当前模块号
 */
static uint8_t can_add_slave_addr(struct can_dev_t *dev,uint32_t addr)
{
    uint8_t i;
  for(i=0;i<MAX_MODULE_COUNT;i++)
  {
      //从机地址 于 设备地址比较
      //记录第一个为0的地址
     //如果比较成功直接return
     if(dev->can_dev_list[i].addr==addr)
     {
       return i;
     }
     if(dev->can_dev_list[i].addr==0x00)
     {
       dev->can_dev_list[i].addr = addr;
       return i;
     }
  }
  return 0xff;
}

/*
 * @检查can 设备地址 是否在canlist 中
 * return 当前模块号
 */
static uint8_t can_add_slave1_addr(struct can_dev_t *dev)
{
	dev->can_dev_list[0].addr=11;
	dev->can_dev_list[1].addr=12;
  return 0xff;
}

/*
 *  @ 根据地址查找模块编号
 * return 当前模块号
 */
static uint8_t can_find_slave(struct can_dev_t *dev,uint32_t addr)
{
 // uint8_t i;
  //for(i=0;i<MAX_MODULE_COUNT;i++)
  //{
  //   if(dev->can_dev_list[i].addr==addr)
  //   {
  //     return i;
  //   }
  //}
	if(addr == 11)return 0;
	if(addr == 12)return 1;
  return 0xff;

}
 void app_can_init(void)
{
    can_init(&comm_dev);
	  can_add_slave1_addr(comm_dev);
		can_app_set_mod_power(comm_dev,0,0);
		can_app_set_mod_power(comm_dev,1,0);
}
/**
 * @brief can 通信逻辑运算
 *        协议参考doc/can_protocol.md
 * 
 */
void app_can_loop_func(void)
{
    uint32_t ext_id;
    uint8_t i;

    if(comm_dev->rx_finish(comm_dev))
    {
        
			  //bit 22~27 cmd 
			  //bit 21~20 src
        ext_id = comm_dev->obj.rx_id;
        comm_dev->obj.slave_addr =  ext_id&0x000fffff;//本机地址
        comm_dev->obj.master_addr = (ext_id>>20)&0x3;//取2bit
        comm_dev->obj.cmd_num = (ext_id>>22)&0xef;//取7bit
				
		//if(comm_dev->obj.master_addr==CAN_MASTER_PROBE_ADDR)//探针地址
    //    {
    //    
    //       //保存探针地址
    //        i=can_add_slave_addr(comm_dev,comm_dev->obj.slave_addr);
    //        if(i==0xff)return  ;
    //        else return ;
		//}
			
			if(comm_dev->obj.slave_addr<10)//地址在保护地址区（0~9） 直接返回
			return ;
			i=can_find_slave(comm_dev,comm_dev->obj.slave_addr);
			if(i==0xff)return ;
			can_read_slave_device_info(comm_dev,i);
    }
}

